<template>
  <div class="page-main">
    <el-col class="grid" :span="7">
      <!-- 左侧输入框 -->
      <div class="leftMainBox audio-data-area">
        <!-- 提示语 -->
        <div class="user-info">
          <span class="username"
            >我是<span>语音转文字</span>智能向导，请说出您的需求？</span
          >
        </div>
        <div class="speak">
          <div
            :key="index"
            @click="meetingFunction(item)"
            v-for="(item, index) in dialogueList"
            :class="{
              speak_left: item.role == 'ai',
              speak_right: item.role == 'user',
            }"
          >
            <div class="img1">
              <img v-if="item.role == 'ai'" src="@/assets/images/jqr2x.png" alt="" />
              <img v-else src="@/assets/images/user2x.png" alt="" />
            </div>
            <div class="audio-data-title">
              <img
                v-show="item.role == 'ai'"
                src="@/assets/images/text2x.png"
                alt="文件"
              />{{ item.content }}
            </div>
          </div>
        </div>
        <!-- 输入框 -->
        <div class="input-area">
          <el-input
            v-model="newMessage"
            placeholder="请输入消息..."
            @keyup.enter.native="sendMessage"
            @click.stop="toggleVoiceInput"
            style="width: 85%"
          ></el-input>
          <!-- 发送按钮放在语音输入按钮后面 -->
          <div class="btns">
            <img src="@/assets/images/audio2x.png" alt="" @click="toggleVoiceInput" />
            <img src="@/assets/images/send2x.png" alt="" @click="sendMessage" />
          </div>
        </div>
      </div>
    </el-col>

    <el-col class="grid" :span="17">
      <!-- 右侧内容框 -->
      <div class="mainBox" v-show="!isEdit">
        <div class="btnLine">
          <!-- <el-button type="text" class="searchIcon" title="搜索"></el-button> -->
          <!-- <el-button type="text" class="contrastIcon" title="对比"></el-button> -->
          <el-button
            type="text"
            class="copyIcon"
            title="复制"
            @click="copyContent"
          ></el-button>
          <el-button
            @click="downloadPage"
            type="text"
            class="downLoadIcon"
            title="下载"
          ></el-button>
          <!-- <el-button @click="downloadPage" type="text">
            <i
              style="color: #fff; font-size: 24px; margin-top: -25px"
              class="el-icon-house"
            ></i>
          </el-button> -->
          <el-button
            @click="toHome"
            type="text"
            class="homeIcon"
            title="回到首页"
          ></el-button>
        </div>
        <div class="mains" id="scrollFlag">
          <h3>{{ meetingTitle }}</h3>
          <vue-markdown
            :source="meetingMinutes"
            id="scrollFlag"
            :html="true"
          ></vue-markdown>

          <!-- 生成公文时展示 -->
          <div v-if="chunkFlag" class="generate-report-loading">
            <span class="prefix-margin">文章生成中 <i class="el-icon-loading"></i></span>
            <span class="span">停止生成</span>
          </div>
        </div>

        <div
          class="bottom"
          :style="{
            display: isTemplateDisabled ? 'none' : 'block',
          }"
        >
          <div class="robotTalk" @click="openDialog">
            <span>{{ "切换模版" }}</span>
            点这里
          </div>
          <div class="robot">
            <img src="~@/assets/images/robot.png" alt="机器人" />
          </div>
        </div>
      </div>
      <!-- <EditMain v-show="isEdit" /> -->
    </el-col>
    <el-dialog
      title="文档转写"
      :visible.sync="dialogVisible"
      width="80%"
      custom-class="darkDialog"
      :append-to-body="true"
      :before-close="handleClose"
    >
      <div>
        <el-row>
          <el-col class="label">请选择模版：</el-col>
          <el-col :span="24" class="modelList">
            <div class="scroll-container" ref="scrollWrap">
              <div class="scroll-content">
                <div
                  v-for="(item, index) in modelList"
                  :key="index"
                  class="modelbox"
                  @click="selectModel(item.id)"
                >
                  <img
                    v-if="curModel == item.id"
                    src="~@/assets/images/curModel.png"
                    :alt="item.templatename"
                  />
                  <img
                    v-else
                    src="~@/assets/images/preModel.png"
                    :alt="item.templatename"
                  />
                  <p :title="item.templatename">{{ item.templatename }}</p>
                </div>
              </div>
            </div>
          </el-col>
        </el-row>
        <el-row>
          <el-col class="label">请选择模版：</el-col>
          <el-col :span="10">
            <el-upload
              action="#"
              :multiple="false"
              :auto-upload="false"
              :on-change="handleChange"
              :file-list="fileList"
              :show-file-list="true"
              ref="upload"
            >
              <el-button class="upLoad-btn"
                ><img src="~@/assets/images/upLoad-file-icon.png" alt="" /><span
                  >上传</span
                ></el-button
              >
            </el-upload>
          </el-col>
        </el-row>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button class="dialog-btn" @click="ProductionReport">开始生成</el-button>
        <el-button class="dialog-btn" @click="handleClose">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
// import LeftBox from "./components/leftBox";
// import EditMain from './components/EditMain'
import BScroll from "better-scroll";
import axios from "axios";
import VueMarkdown from "vue-markdown";
export default {
  name: "speechToText",
  components: {
    // LeftBox,
    // EditMain,
    VueMarkdown,
  },
  data() {
    return {
      streamReader: null, // 添加streamReader引用
      isEdit: false, // 是否编辑模式
      meetingTitle: "", // 名称
      meetingMinutes: "", // 内容
      dialogVisible: false, // 切换模版
      modelList: [],
      curModel: null, // 选中的模版
      scroll: null, // 用于存储better-scroll实例
      fileList: [],
      meetingData: "",
      dialogueList: [],
      newMessage: "", // 新消息输入框
      meetingMinutesDetil: "",
      isTemplateDisabled: false, // 控制“切换模版”按钮的禁用状态
      AudiofilesId: "",
      conversationHistory: [], // 存储对话历史记录
      currentConversationId: null, // 当前显示的对话ID
      chunkFlag: false,
    };
  },
  created() {
    this.AudiofilesId = this.getFieldIdFromSessionStorage();
  },
  mounted() {
    this.meetingMinutes = localStorage.getItem("speechToTextContent"); // 初始化会议纪要内容
    this.meetingTitle = `原始文件名称:${localStorage.getItem("filename")}`; // 查看的文件名
    this.dialogueList.push({
      role: "ai",
      content: "这里是原始音频文档",
      id: "1",
      resultContent: this.meetingMinutes,
    });
    this.getAllModelDetil();
  },
  methods: {
    // 从 sessionStorage 中获取 fieldId
    getFieldIdFromSessionStorage() {
      return sessionStorage.getItem("fieldId");
    },
    // 左侧输入区会议切换
    meetingFunction(item) {
      if (item.id == "1") {
        this.meetingMinutes = item.resultContent;
      } else {
        if (this.conversationHistory.length > 0) {
          let res = this.conversationHistory.filter(
            (item2) => item2.conversationId == item.conversationId
          );
          if (item.role === "user" || item.role === "ai") {
            this.meetingMinutes = res[0].resultContent;
          }
        }
      }
    },
    // 发送消息
    sendMessage() {
      if (this.newMessage.trim()) {
        const conversationId = Date.now().toString(); // 生成唯一对话ID
        this.currentConversationId = conversationId;
        this.dialogueList.push({
          role: "user",
          content: this.newMessage,
          conversationId: conversationId,
        });
        this.conversationHistory.push({
          conversationId: conversationId,
          userMessage: this.newMessage,
        });
        this.newMessage = "";
        this.toSpeechText(
          {
            query: this.newMessage,
            content: this.meetingMinutesDetil,
            requestid: "",
          },
          conversationId
        );
      }
    },
    // 润色接口调用
    toSpeechText(parms, conversationId) {
      fetch("/gt/chat/polishdoc", {
        method: "POST",
        body: JSON.stringify(parms),
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          this.chunkFlag = true;

          if (!response.ok) {
            throw new Error("Network response was not ok");
          }
          return response.body; // 获取流式响应
        })
        .then((stream) => {
          this.streamReader = stream.getReader();
          const decoder = new TextDecoder("utf-8");
          let accumulatedData = ""; // 用于存储完整的字符串
          const read = () => {
            return this.streamReader.read().then((result) => {
              if (result.done) {
                this.chunkFlag = false;

                // this.getMetingtemplate(accumulatedData, "");
                this.dialogueList.push({
                  role: "ai",
                  content: `这里是润色后的结果(${conversationId})`,
                  conversationId: conversationId,
                  resultContent: accumulatedData,
                });
                // 保存AI回复内容
                if (this.conversationHistory.length > 0) {
                  const lastIndex = this.conversationHistory.length - 1;
                  this.conversationHistory[lastIndex].resultContent = accumulatedData;
                }
                this.isTemplateDisabled = true; // 接口调通后禁用“切换模版”按钮
                return;
              }
              const chunk = decoder.decode(result.value, { stream: true });
              accumulatedData += chunk; // 累积数据
              this.meetingMinutes = accumulatedData; // 渲染最终数据

              return read(); // 继续读取下一块数据
            });
          };
          read();
        });
    },
    // 滚动底部
    scrollToBottom() {
      this.$nextTick(() => {
        setTimeout(() => {
          var div = document.getElementById("scrollFlag");
          if (div.scrollHeight) {
            div.scrollTop = div.scrollHeight;
          }
        }, 500);
      });
    },
    // 选择模板生成会议纪要
    getMetingtemplate(templatedata, templateId) {
      this.meetingMinutes = "";
      const query = "生成会议纪要";
      const templateid = templateId ? templateId : "2bb5e02325924a6fa23c0dea8a16d02b";
      const requestid = "";
      const content = templatedata;
      const wordCountParms = {
        query,
        templateid,
        requestid,
        content,
      };

      fetch("/gt/chat/chatmeetingbytemplate", {
        method: "POST",
        body: JSON.stringify(wordCountParms),
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          this.chunkFlag = true;

          if (!response.ok) {
            throw new Error("Network response was not ok");
          }
          return response.body; // 获取流式响应
        })
        .then((stream) => {
          this.streamReader = stream.getReader();
          const decoder = new TextDecoder("utf-8");
          let accumulatedData = ""; // 用于存储完整的字符串
          const read = () => {
            return this.streamReader.read().then((result) => {
              if (result.done) {
                this.chunkFlag = true;

                //  this.meetingMinutes = res.data.split("/think>")[1];
                window.meetingMinutesData = this.meetingMinutes;
                return;
              }
              this.scrollToBottom();
              const chunk = decoder.decode(result.value, { stream: true });
              accumulatedData += chunk; // 累积数据
              this.meetingMinutes = accumulatedData; // 渲染最终数据
              return read(); // 继续读取下一块数据
            });
          };
          read();
        });
    },

    //todo 获取单个语音文件转文字详情
    getAllModelDetil() {
      axios({
        method: "get",
        url: this.BaseApi + `/gt/util/queryfileinfo?fileid=` + this.AudiofilesId,
      }).then((res) => {
        if (res.status === 200) {
          const conText = res.data.data.map((item) => item.data).join("");
          this.meetingMinutesDetil = conText;
        } else {
          this.$message({
            showClose: true,
            message: "请求失败!",
          });
        }
      });
    },

    // 开始生成会议纪要
    ProductionReport() {
      if (this.curModel) {
        this.dialogVisible = false;
        this.getMetingtemplate(this.meetingMinutesDetil, this.curModel);
      } else {
        this.$message({
          type: "warning",
          showClose: true,
          message: "请先选择一个模板!",
        });
      }
    },
    // 切换语音输入状态
    toggleVoiceInput() {
      if (!this.recognition) {
        console.error("语音识别功能不可用");
        return;
      }
      this.isVoiceInputActive = !this.isVoiceInputActive;
      if (this.isVoiceInputActive) {
        this.recognition.start();
      } else {
        this.recognition.stop();
      }
    },
    // 模版列表滚动
    initScroll() {
      var scrollWrap = this.$refs.scrollWrap;
      if (scrollWrap) {
        this.scroll = new BScroll(scrollWrap, {
          scrollX: true,
          scrollY: false,
          click: true,
          probeType: 5,
          mouseWheel: true, // 鼠标滚轮滚动
          disableMouse: false, // 启用鼠标拖动
          disableTouch: false, // 启用手指触摸
        });
      }
    },

    // 下载
    downloadPage() {
      const content = this.meetingMinutes;
      const blob = new Blob([content], { type: "application/msword" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `会议纪要.doc`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      this.$message.success("下载成功");
    },
    // 开启文档转写
    openDialog() {
      this.getList();
      this.dialogVisible = true;
      this.$nextTick(() => {
        this.initScroll();
      });
    },
    // 关闭文档转写
    handleClose() {
      this.dialogVisible = false;
    },
    // 选中模版
    selectModel(value) {
      this.curModel = value;
    },
    // 上传文件更改
    handleChange(file, fileList) {
      file.status = "uploading";
      file.percentage = 0;
      const isLt5M = file.size / 1024 / 1024 <= 200;
      const isFormat =
        file.raw.type ===
          "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ||
        file.raw.type === "application/msword" ||
        file.raw.type === "application/pdf" ||
        file.raw.type === "text/plain";
      if (fileList.length > 1) {
        this.$message.error("请先选择文件！");
      }

      if (!isLt5M) {
        this.$message.error("上传的文件大小不能超过 200MB!");
        fileList.pop();
        return false;
      }

      if (!isFormat) {
        this.$message.error("上传的文件必须为word或pdf格式或txt格式!");
        fileList.pop();
        return false;
      }
      let formdata = new FormData();
      formdata.append("file", file.raw);
      const templatetypes = "audio";
      const config = {
        onUploadProgress: (progressEvent) => {
          file.percentage = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          this.$forceUpdate();
        },
      };
      axios({
        method: "post",
        url: `/gt/util/uploadtemplate?templatename=${file.name}&templatetype=${templatetypes}`,
        data: formdata,
        ...config,
      }).then((res) => {
        if (res.data.success) {
          this.$message({
            showClose: true,
            message: "上传文件成功!",
            type: "success",
          });
          file.status = "success";
          file.percentage = 100;
          this.fileList = fileList;
          this.getList();
        } else {
          file.status = "error";
          this.$message({
            showClose: true,
            message: "上传文件失败!",
            type: "error",
          });
          this.fileMeetingList = [];
        }
      });
      return true;
    },
    // 查询模板列表
    getList() {
      axios({
        method: "get",
        url: `/gt/util/querytemplatelist?templatetype=` + "audio",
      }).then((res) => {
        if (res.data.success) {
          this.modelList = res.data.data;
        } else {
          this.$message.error(res.data.msg);
        }
      });
    },
    // 复制
    copyContent() {
      const textarea = document.createElement("textarea");
      textarea.value = this.meetingMinutes;
      document.body.appendChild(textarea);
      textarea.select();
      document.execCommand("copy");
      document.body.removeChild(textarea);
      this.$message.success("复制成功");
    },
    // 回到首页
    toHome() {
      this.$router.push({ path: "/home" });
    },
    // 停止生成
    stopGeneration() {
      if (this.streamReader) {
        this.streamReader.cancel(); // 取消流式读取
        this.streamReader = null;
        this.chunkFlag = false;
      }
    },
  },
};
</script>
<style lang="less" scoped>
.page-main {
  width: 100%;
  height: 100%;
  color: #fff;
  background-size: 100% 100%;
  border: 1px solid #096391;
  //background-color: rgba(4, 20, 34, 0.6);
  background-color: #061428;
}
.grid {
  height: 100%;
}
.page-main > .grid:first-of-type {
  width: 30%;
}
.page-main > .grid:nth-of-type(2) {
  width: 70%;
}
.mainBox {
  border: 1px solid #096391;
  padding: 19px 28px;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.btnLine {
  height: 24px;
  width: 100%;
  display: flex;
  justify-content: end;
}
::v-deep .btnLine .el-button {
  width: 24px;
  height: 24px;
  margin-left: 14px;
  background-color: rgba(0, 0, 0, 0);
}
.searchIcon {
  background: url("~@/assets/images/searchIcon.png") no-repeat;
  background-size: 100% 100%;
}
.contrastIcon {
  background: url("~@/assets/images/contrastIcon.png") no-repeat;
  background-size: 100% 100%;
}
.copyIcon {
  background: url("~@/assets/images/copyIcon.png") no-repeat;
  background-size: 100% 100%;
}
.downLoadIcon {
  background: url("~@/assets/images/downLoadIcon.png") no-repeat;
  background-size: 100% 100%;
}
.homeIcon {
  background: url("~@/assets/images/首页.png") no-repeat;
  background-size: 100% 100%;
}
.mains {
  flex: 1;
  overflow-y: auto;
}
.mains h3 {
  text-align: center;
}
.text {
  text-indent: 2em;
  font-size: 20px;
}
.bottom {
  height: 168px;
  position: absolute;
  bottom: 10px;
  right: 10px;
}
.robotTalk {
  position: absolute;
  top: 0px;
  right: 56px;
  width: 180px;
  height: 60px;
  background: url("~@/assets/images/robotTalk-bg.png") no-repeat;
  background-size: 100% 100%;
  box-sizing: border-box;
  padding: 14px 20px;
  font-size: 18px;
  cursor: pointer;
}
.robotTalk span {
  color: #14b8fd;
  font-weight: bold;
  font-size: 18px;
}
.robot {
  position: absolute;
  width: 87px;
  height: 114px;
  bottom: 0;
  right: 0;
}
.robot img {
  width: 100%;
  height: 100%;
  cursor: pointer;
}
.dialog-btn {
  width: 90px;
  height: 40px;
  font-size: 16px;
  color: #fff;
  background: url("~@/assets/images/dialog-btn.png") no-repeat;
  background-size: 100% 100%;
  border-width: 0px !important;
  padding: 12px 0px;
  text-align: center;
}
// 弹框样式
::v-deep .darkDialog {
  background: rgb(2, 12, 21, 0.6);
  border: 2px solid #26a9f9;
  border-radius: 0px;
  color: #fff;
  .el-dialog__header {
    background: rgba(70, 167, 255, 0.4);
    border-bottom: 2px solid #26a9f9;
    padding: 0px 22px;
    height: 48px;
  }
  .el-dialog__title {
    line-height: 48px;
    font-size: 18px;
    color: #fff;
  }
  .el-dialog__headerbtn {
    display: none;
  }
}
.label {
  width: 130px;
  font-size: 16px;
  line-height: 24px;
  color: #fff;
}
.modelList {
  height: 331px;
  width: 92%;
  box-sizing: border-box;
  margin: 10px 4%;
  padding: 0 100px 30px 100px;
  margin-bottom: 38px;
  display: block;
  overflow: hidden;
  background: url("~@/assets/images/modelList-bg.png") no-repeat;
  background-position: center bottom;
  background-size: 100% auto;
  .scroll-container {
    width: 100%;
    overflow: hidden;
  }
  .scroll-content {
    height: 271px;
    display: flex; /* 使用flexbox使内容横向排列 */
    width: max-content; /* 让内容的宽度自适应内容 */
  }
  .modelbox {
    width: 170px;
    height: 271px;
    background-color: lightblue;
    margin: 0px 25px;
    display: inline-block;
    overflow: hidden;
    background: url("~@/assets/images/modelbox-bg.png");
    background-size: 100% 100%;
    cursor: pointer;
    img {
      display: block;
      width: 126px;
      height: 131px;
      margin: 30px auto;
    }
    p {
      line-height: 24px;
      text-align: center;
      font-size: 18px;
      color: rgba(248, 252, 255, 0);
      line-height: 26px;
      text-shadow: 0px 3px 0px rgba(0, 103, 156, 0.33), 0px 3px 5px rgba(6, 13, 16, 0.7);
      background: linear-gradient(0deg, #7cd0ff 0%, #feffff 100%);
      background-clip: text;
      color: transparent;
      padding: 0 20px;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
}
.upLoad-btn {
  background: rgba(2, 12, 21, 0.8);
  border: 2px solid #26a9f9;
  border-radius: 10px;
  height: 36px;
  padding: 6px 20px;
  color: #fff;
  img {
    width: 16px;
    height: 18px;
  }
}

/deep/ input[type="file"] {
  display: none;
}

/deep/.el-upload-list__item-name {
  color: #fff;
}
/deep/.el-upload-list__item:hover {
  background-color: inherit;
}
/deep/.el-upload-list__item .el-icon-close {
  color: #fff;
}

.leftMainBox {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: 22px 32px;
  border: 1px solid #096391;
}
.audio-data-area {
  display: flex;
  flex-direction: column;

  .speak_right {
    text-align: right;

    .audio-data-title {
      display: inline-block;
    }
  }

  .user-info {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
  }

  .speak {
    flex: 1;
    overflow-y: auto;
  }

  .username {
    font-weight: bold;
    font-size: 22px;

    span {
      color: #3fb0ff;
    }
  }

  .audio-data-title {
    width: fit-content;
    font-size: 14px;
    margin-bottom: 20px;
    padding: 5px 10px;
    border-radius: 10px;
    box-sizing: border-box;
    background: rgba(250, 250, 250, 0.15);
    vertical-align: middle;
    margin-top: 8px;
    cursor: pointer;

    img {
      margin-right: 5px;
      vertical-align: middle;
    }
  }

  .audio-data-title.polish {
    background: rgba(255, 207, 15, 0.2);
  }

  .input-area {
    position: fixed;
    bottom: 20px;
    left: 2%; /* 根据左侧区域宽度调整 */
    width: 26%;
    padding: 10px;
    box-sizing: border-box;
    border: 1px solid #096391;
    height: 50px;
    border-radius: 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .btns {
      width: 15%;
      cursor: pointer;

      img {
        margin-right: 10px;
      }
    }

    ::v-deep .el-input__inner {
      background: none;
      color: #fff;
      border: none;
    }
  }
}
/deep/.el-loading-mask {
  background-color: transparent !important;
}
.generate-report-loading {
  display: flex;
  justify-content: space-between;
  background-color: #061428;
  border: 1px solid #26a9f9;
  border-radius: 6px;
  height: 28px;
  line-height: 28px;
  align-items: center;
  /* 垂直居中对齐 */
  padding: 20px;

  .span {
    border: 1px solid #26a9f9;
    width: 65px;
    border-radius: 8px;
    text-align: center;
    margin-right: 16px;
    /* 或者 2ch */
    cursor: pointer;
  }
}
</style>
